/*
 *  The paging.c source file implements memory pagination functions
 */

//local includes
#include <i386_paging.h>


/* Paging Structure Management Functions Implementation */

// Page Table

void ivmmPTE_setAccess(PTE_T *entry,byte_t value)
  {
    entry->access=value;
  }

byte_t ivmmPTE_getAccess(PTE_T *entry)
  {
    return entry->access;
  }

void ivmmPTE_setOsBits(PTE_T *entry,byte_t value)
  {
    //entry->pfraddr_lsb|=(value&0x07)<<1;   //error
    entry->pfraddr_lsb=(entry->pfraddr_lsb&0xF0)|((value&0x07)<<1);
  }

byte_t ivmmPTE_getOsBits(PTE_T *entry)
  {
    return (entry->pfraddr_lsb>>1)&0x07;
  }

void ivmmPTE_setAddress(PTE_T *entry,dword_t address)
  {
    //dword_t value;

    //Get old value
    //value=(((dword_t)entry->pfraddr_lsb&0x0F)<<8)|entry->access;  // &0x0F to keep the OS reserved bits and the 0

    //Since address is page-aligned (first 12 bits are zeroes) then we can use a little trick...    
    //entry->access=address|value;    

    entry->pfraddr_msb=address>>16;
    entry->pfraddr_lsb=(address&0xF000)>>8;

  }

dword_t ivmmPTE_getAddress(PTE_T *entry)
  {
    return (dword_t)((dword_t)entry->pfraddr_msb<<16 | (dword_t)(entry->pfraddr_lsb&0xF0)<<8);
  }


// Page Directory

void ivmmPDE_setAccess(PDE_T *entry,byte_t value)
  {
    entry->access=value;
  }

byte_t ivmmPDE_getAccess(PDE_T *entry)
  {
    return entry->access;
  }

void ivmmPDE_setOsBits(PDE_T *entry,byte_t value)
  {
    entry->pteaddr_lsb=(entry->pteaddr_lsb&0xF0)|((value&0x07)<<1);
  }

byte_t ivmmPDE_getOsBits(PDE_T *entry)
  {
    return (entry->pteaddr_lsb>>1)&0x07;
  }

void ivmmPDE_setAddress(PDE_T *entry,dword_t address)
  {
    //dword_t value;
    //word_t tmp;

    //Get old value
    //value=(((dword_t)entry->pteaddr_lsb&0x0F)<<8)|entry->access;  // &0x0F to keep the OS reserved bits and the 0

    //Since address is page-aligned (first 12 bits are zeroes) then we can use a little trick...    
    //entry->access=address|value;    

    /*
    tmp=address>>16;
    entry->pteaddr_msb=tmp;
    tmp=(address&0xF000)>>8;
    entry->pteaddr_lsb=tmp;
    */


    entry->pteaddr_msb=address>>16;
    entry->pteaddr_lsb=(address&0xF000)>>8;

  }

dword_t ivmmPDE_getAddress(PDE_T *entry)
  {
    dword_t x,y,z;

    x=entry->pteaddr_msb;
    x<<=16;
    y=entry->pteaddr_lsb&0xF0;
    y<<=8;
    z=x|y;
    return z;

    
    //return (dword_t)((dword_t)entry->pteaddr_msb<<16 | (dword_t)(entry->pteaddr_lsb&0xF0)<<8);
  }
